﻿using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using Abp.IdentityServer4;
using Abp.Zero.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;
using abpAngular.Authorization.Roles;
using abpAngular.Authorization.Users;
using abpAngular.Chat;
using abpAngular.DataDictionary;
using abpAngular.Editions;
using abpAngular.Friendships;
using abpAngular.MultiTenancy;
using abpAngular.MultiTenancy.Accounting;
using abpAngular.MultiTenancy.Payments;
using abpAngular.Storage;
using abpAngular.EntityMapper.SubscriptionPayments;

namespace abpAngular.EntityFrameworkCore
{
    public partial class AbpFrameDbContext : AbpZeroDbContext<Tenant, Role, User, AbpFrameDbContext>, IAbpPersistedGrantDbContext
    {
        /* Define an IDbSet for each entity of the application */

        public virtual DbSet<BinaryObject> BinaryObjects { get; set; }

        public virtual DbSet<Friendship> Friendships { get; set; }

        public virtual DbSet<ChatMessage> ChatMessages { get; set; }

        public virtual DbSet<SubscribableEdition> SubscribableEditions { get; set; }

        public virtual DbSet<SubscriptionPayment> SubscriptionPayments { get; set; }

        public virtual DbSet<Invoice> Invoices { get; set; }

        public virtual DbSet<PersistedGrantEntity> PersistedGrants { get; set; }

        public DbSet<DictionaryItem> DictionaryItems { get; set; }
        public DbSet<DictionaryValue> DictionaryValues { get; set; }


        public AbpFrameDbContext(DbContextOptions<AbpFrameDbContext> options)
            : base(options)
        {
            
        }

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            #region 设置自定义表表前缀

            //var entityTypes = modelBuilder.Model.GetEntityTypes().ToList();
            //foreach (var entityType in entityTypes)
            //{
            //    var tableAttribute = entityType.ClrType.GetCustomAttributes(typeof(TableAttribute), true)
            //        .FirstOrDefault();
            //    if (tableAttribute is TableAttribute)
            //    {
            //        //如果设置了表名特性，就跳过
            //        continue;
            //    }

            //    string tableName = AbpFrameConsts.DbTablePrefix.APP + "." + entityType.ClrType.Name;
            //    modelBuilder.Entity(entityType.ClrType).ToTable(tableName);
            //}

            #endregion

            #region 设置abp内置表表前缀
            modelBuilder.ChangeAbpTablePrefix<Tenant, Role, User>(AbpFrameConsts.DbTablePrefix.Base);
            // identityServer4
            modelBuilder.ConfigurePersistedGrantEntity(AbpFrameConsts.DbTablePrefix.Base);
            // 订阅支付
            modelBuilder.ApplyConfiguration(new SubscriptionPaymentCfg());
            #endregion
            base.OnModelCreating(modelBuilder);

            modelBuilder.Entity<BinaryObject>(b =>
            {
                b.HasIndex(e => new { e.TenantId });
            });

            modelBuilder.Entity<ChatMessage>(b =>
            {
                b.HasIndex(e => new { e.TenantId, e.UserId, e.ReadState });
                b.HasIndex(e => new { e.TenantId, e.TargetUserId, e.ReadState });
                b.HasIndex(e => new { e.TargetTenantId, e.TargetUserId, e.ReadState });
                b.HasIndex(e => new { e.TargetTenantId, e.UserId, e.ReadState });
            });

            modelBuilder.Entity<Friendship>(b =>
            {
                b.HasIndex(e => new { e.TenantId, e.UserId });
                b.HasIndex(e => new { e.TenantId, e.FriendUserId });
                b.HasIndex(e => new { e.FriendTenantId, e.UserId });
                b.HasIndex(e => new { e.FriendTenantId, e.FriendUserId });
            });

            modelBuilder.Entity<Tenant>(b =>
            {
                b.HasIndex(e => new { e.SubscriptionEndDateUtc });
                b.HasIndex(e => new { e.CreationTime });
            });

            modelBuilder.Entity<SubscriptionPayment>(b =>
            {
                b.HasIndex(e => new { e.Status, e.CreationTime });
                b.HasIndex(e => new { PaymentId = e.ExternalPaymentId, e.Gateway });
            });
        }
    }
}
